﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ReporterApplication
{
    public class rSelectorParser
    {
        // #$ property, filter [filtering] 

        public static readonly Regex findNonAlpha = new Regex("[\\#\\$]");

        public rSelectorNode Parse(string selector)
        {
            //parse all incrementally
            var currentNode = new rSelectorNode();
            var resultNode = currentNode;
            
            int position = 0;

            var stack = new Stack<rSelectorNode>();

            while(position < selector.Length)
            {
                char? currentChar = selector[position];

                bool skip = false;

                if (selector.Length - position > 1)
                {
                    string currentStr = selector.Substring(position, 2);

                    switch (currentStr)
                    {
                        case "==":
                            position ++;
                            skip = true;

                            var exp = (rExpNode)currentNode.Parent;
                            exp.expString = "==";
                            exp.SelectorText = "==";

                            exp.Right = new rSelectorNode();

                            currentNode = exp.Right;

                            break;
                    }
                }

                if (!skip)
                {
                    switch (currentChar)
                    {
                        case '#':
                            var newProperty = rSelectorNode.NewNextNode(currentNode);
                            currentNode = newProperty;

                            currentNode.SelectorText += currentChar;
                            break;
                        case '$':
                            var newFilter = rSelectorNode.NewNextNode(currentNode);
                            currentNode = newFilter;

                            currentNode.SelectorText += currentChar;
                            break;

                        case ':':
                            var newMethod = new rMethodNode();
                            currentNode.Next = newMethod;
                            newMethod.Parent = currentNode;
                            currentNode = newMethod;

                            currentNode.SelectorText += currentChar;
                            break;

                        case '[':
                            stack.Push(currentNode);

                            var leftNode = new rSelectorNode();

                            var expNode = new rExpNode();
                            expNode.Left = leftNode;

                            leftNode.Parent = expNode;

                            expNode.Parent = currentNode;
                            currentNode.Filter = expNode;

                            currentNode = leftNode;
                            break;
                        case ']':
                            currentNode = stack.Pop();
                            break;

                        case '(':
                            stack.Push(currentNode);

                            var startParameter = rSelectorNode.NewNode(currentNode);
                            ((rMethodNode)currentNode).Parameters = startParameter;
                            startParameter.Parent = currentNode;
                            currentNode = startParameter;
                            break;
                        case ')':
                            currentNode = stack.Pop();
                            break;



                        default:
                            currentNode.SelectorText += currentChar;
                            break;
                    }
                }

                position++;
            }
            
            return resultNode;
        }
    }
}
